package at.fhooe.mc.master.clc.server.dataaccess.dao.jpa;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import at.fhooe.mc.master.clc.server.dataaccess.dao.ITestableDao;
import at.fhooe.mc.master.clc.server.domain.ITestable;

public class TestableJpaDao implements ITestableDao
{
	@Override
	public int save(ITestable testable)
	{
		EntityManager em = EMF.get().createEntityManager();

		try
		{
			em.persist(testable);
		} finally
		{
			em.close();
		}

		return 0;
	}

	@Override
	public int save(List<ITestable> testables)
	{
		for (ITestable testable : testables)
			save(testable);
		
		return 0;
	}

	@Override
	public List<? extends ITestable> loadAll(Class<? extends ITestable> type)
	{
		EntityManager em = EMF.get().createEntityManager();
		List<? extends ITestable> list = null;
		
		try
		{
			Query q = em.createQuery("SELECT t FROM " + type.getSimpleName() + " t");
			list = q.getResultList();

		} finally
		{
			em.close();
		}
		
		return list;
	}

	@Override
	public List<? extends ITestable> loadFilteredEquals(
			Class<? extends ITestable> type, String field1, Object filter1,
			String field2, Object filter2, String field3, Object filter3,
			String field4, Object filter4)
	{
		EntityManager em = EMF.get().createEntityManager();
		List<? extends ITestable> list = null;
		
		try
		{
			// prepare query
			String queryString = "SELECT t FROM " + type.getSimpleName() + " t WHERE ";
			if (field1 != null)
			{
				queryString += "t." + field1 + " = :" + field1 + " And ";
			} else if (field2 != null)
			{
				queryString += "t." + field2 + " = :" + field2 + " And ";
			} else if (field3 != null)
			{
				queryString += "t." + field3 + " = :" + field3 + " And ";
			} else if (field4 != null)
			{
				queryString += "t." + field4 + " = :" + field4 + " And ";
			}

			if (queryString.contains("And"))
			{
				// cut away the last '&&'
				queryString = queryString.substring(0,
						queryString.lastIndexOf("And") - 1);
			}
			
//			System.out.println("## Query: " + queryString);

			Query q = em.createQuery(queryString);

			// set parameters
			if (field1 != null)
			{
				q.setParameter(field1, filter1);
			} else if (field2 != null)
			{
				q.setParameter(field2, filter2);
			} else if (field3 != null)
			{
				q.setParameter(field3, filter3);
			} else if (field4 != null)
			{
				q.setParameter(field4, filter4);
			}

			list =  q.getResultList();

		} finally
		{
			em.close();
		}
		
		return list;
	}

	@Override
	public ITestable loadSpecific(Class<? extends ITestable> type, long id)
	{
		EntityManager em = EMF.get().createEntityManager();
		ITestable t = null;
		
		try
		{
			// prepare query
			String queryString = "SELECT t FROM " + type.getSimpleName() + " t"
					+ " WHERE t.id = :id";
			Query q = em.createQuery(queryString);

			q.setParameter("id", id);

			t = (ITestable) q.getSingleResult();

		} finally
		{
			em.close();
		}
		
		return t;
	}

	@Override
	public ITestable loadSpecific(Class<? extends ITestable> type, String id)
	{
		EntityManager em = EMF.get().createEntityManager();

		try
		{
			// prepare query
			String queryString = "SELECT t FROM " + type.getSimpleName() + " t"
					+ " WHERE t.id = :id";
			Query q = em.createQuery(queryString);

			q.setParameter("id", id);

			// set parameters

			return (ITestable) q.getSingleResult();

		} finally
		{
			em.close();
		}
	}

	@Override
	public int delete(ITestable testable,
			Class<? extends ITestable> specificClass)
	{
		EntityManager em = EMF.get().createEntityManager();

		try
		{	
//			String queryString = "SELECT t FROM " + specificClass.getSimpleName()
//					+ " t WHERE " + "t.id = :id";
//			
//			Query q = em.createQuery(queryString);
//			q.setParameter("id", testable.getId());
//			
//			ITestable t = (ITestable)q.getSingleResult();
			
			ITestable t = em.find(specificClass, testable.getId());
			em.remove(t);
		} 
		catch (Exception e)
		{
			e.printStackTrace();
		}
		finally
		{
			em.close();
		}

		return 0;
	}

	@Override
	public int deleteAll(List<ITestable> toBeDeleted)
	{
		for (ITestable testable : toBeDeleted)
			delete(testable, testable.getClass());
		
		return 0;
	}

}
